Obsidian obsidian-git 使用 Git LFS 管理大文件

我使用 obsidian-git 进行 0.0 Obsidian 介绍 笔记同步,随着 Vault 中大文件越来越多,我逐渐开始发愁:Git 并不适合处理大文件。直到我将一个 3.4GB 的视频加入 Vault Git 仓库,直接把 NAS 搞歇菜了……于是我想到了 Git LFS

在本文中,我的目标是:Vault 仍然使用 Git 仓库,但开启 Git LFS,继续使用 obsidian-git 同步。同时,我对提交进行严格限制(通过 pre-commit 钩子),只有纯文本文件能进入 Git 仓库,其他所有二进制都走 LFS,都不会真正提交到 Git 仓库里。从而实现了既保持 Git 仓库的纯粹优雅,又能在 Vault 中存储大量二进制大文件。

我的 Git Server 基于 Gitea 运行在我的 NAS 上,因此容量不是问题。Vault 的大小只取决于我本地电脑硬盘的大小。这也不是问题,正是我所期望的,我希望的就是 0.0 Obsidian 介绍 “存一切”数据。这样,从一台电脑切换到另一台,或者买一台新电脑时,clone 一下 Vault,熟悉的味道,熟悉的感觉,一下子就回来了。


备份数据

折腾前请备份数据

我在探索前,在 NAS 上备份了 Gitea 的 Docker 数据,在电脑上也复制了一份 Vault,并在 Gitea 上创建新 Repo 进行试验。这些操作保证新的尝试不会把已有数据搞损坏,一旦尝试失败,我立刻能回到现有状态,不会有任何损失。

事实证明,这是无比明智的。我在升级 Gitea 时,看容器不响应,手动停止了容器。可实际上 Gitea 正在数据库迁移,迁移一半终止,数据库直接损毁了,无法修复。好在我有备份,复制一份重新迁移,顺利完成。可见备份的重要性


创建 Git LFS 仓库

在本地电脑上,将 Vault 目录复制一份,进入新仓库,删除已有的 .git 目录。在新仓库中重新创建 git 仓库,并开启 LFS 支持:

git init
git lfs install

# 关联远程仓库
git remote add origin ssh://git@仓库地址/maxiee/obsidian-notes-lfs.git

在 Linux 下,当路径中含有中文时,git 会以 "\nnn\nnn..." 的格式展示,导致后续脚本运行失败。具体参见这篇网页。需要进行如下 git 设置:

git config core.quotepath off

二进制文件拦截钩子

这是我这次实践中非常有特色的部分。我只想让 git 管理纯文本文件,二进制都通过 lfs 托管。于是我通过一个 commit 钩子,实现自动拦截未经 LFS 跟踪的二进制文件,从而避免了二进制不小心被添加到 Git 库中,保证了 Git 库里只有纯文本。

在 Vault 的 .git/hooks 内创建如下 pre_commit 文件,它会首先根据一个文本文件的后缀白名单判断,在白名单内表示是纯文本,不拦截提交。如果是被 Git LFS 跟踪的二进制,而不拦截提交。如果都不是,则默认为二进制文件,阻塞提交。这样,开启 obsidian-git 的自动提交,遇到不支持的二进制,也会被拦下来。

#!/bin/sh

echo "正在检查提交的文件..."

# 保存原始的 IFS 值
OLD_IFS="$IFS"
# 只按照换行符分割
IFS=

显然,后缀白名单会导致误判。这没关系,只要手动维护这个白名单即可。

让钩子变为可执行权限:`chmod +x .git/hooks/pre_commit`。

---

## 提交所有 Markdown 文件

首先需要在新仓库中重新提交 Markdown。我有六千多篇 Markdown 笔记,于是我写了个脚本,一键 `git add` 仓库内所有 Markdown:

```sh
#!/bin/bash

# 设置您的 Obsidian Vault 目录的路径
VAULT_PATH="."

# 检查是否有文件扩展名作为参数传入
if [ $# -eq 0 ]; then
  echo "请提供文件扩展名作为参数,例如:'.md'"
  exit 1
fi

EXTENSION=$1

# 寻找所有指定扩展名的文件并添加到 Git 暂存区
find "$VAULT_PATH" -type f -name "*${EXTENSION}" -exec git add {} +

echo "所有 ${EXTENSION} 文件已添加到暂存区。"

这个脚本是通用的,支持任意后缀:./.obsidian/maeiee_scripts/commit_all_markdown.sh .md


尝试 lfs track epub

git lfs track "*.epub"

之后,对 epub 文件正常 add、commit、push 即可,在命令行中能看到 LFS 上传提示。

注:如果不执行 git lfs track,直接上传 Epub,会被 pre-commit 所拦截。

下图是开启 LFS 后的提交截图,性能和速度比起 Git 直接提交,要好上不少:

Pasted image 20240205021126.png

在 Gitea 项目设置的 LFS Tab 中,能够看到二进制文件:

Pasted image 20240205021311.png


尝试 track 大视频

下面尝试添加开头说的那个 3.4GB 的大视频。上传过程中速度非常快(这是我电脑 WIFI 的速度上限):

Uploading LFS objects:  50% (1/2), 3.2 GB | 41 MB/s                                                                           

值得一提的是,这个过程电脑负载非常轻。Server 端压力也小得多。Git 直接处理二进制时,性能开销很大,同时在 Server 侧需要申请大量内存。而有了 Git LFS,实际上就是一个接口文件上传的事情。


暂时关闭 obsidian-git 自动同步

这套系统配置好后,我准备手动同步一段时间。在这段时间里,细细查看过程中是否有什么问题。等到未来,打磨流畅、有了足够信心后,再将 obsidian-git 自动同步打开,这件事情便彻底完结了。


新电脑配置 Todo

未来新电脑需要 clone repo 时,需要遵循以下步骤:

  1. 电脑安装 Git LFS
  2. clone 仓库
  3. 需要手动复制 pre-commit 脚本,放入 .git/hooks 目录下

\n'

for file in $(git diff --cached --name-only); do

如果文件是 Markdown 文件,始终视为文本文件

if json; then
continue
fi

检查文件是否被 Git LFS 跟踪

lfs_attr=(gitcheckattrfilter"file")
if [[ $lfs_attr == "lfs" ]]; then
continue
fi

echo "错误: 文件 '$file' 不是文本文件,也未通过 Git LFS 跟踪。"
exit 1
done

恢复原始的 IFS 值

IFS="$OLD_IFS"

如果所有检查都通过,则允许提交

exit 0


显然,后缀白名单会导致误判。这没关系,只要手动维护这个白名单即可。

让钩子变为可执行权限:`chmod +x .git/hooks/pre_commit`。

---

## 提交所有 Markdown 文件

首先需要在新仓库中重新提交 Markdown。我有六千多篇 Markdown 笔记,于是我写了个脚本,一键 `git add` 仓库内所有 Markdown:

{{CODE_BLOCK_3}}

这个脚本是通用的,支持任意后缀:`./.obsidian/maeiee_scripts/commit_all_markdown.sh .md`。

---

## 尝试 lfs track epub

{{CODE_BLOCK_4}}

之后,对 epub 文件正常 add、commit、push 即可,在命令行中能看到 LFS 上传提示。

注:如果不执行 `git lfs track`,直接上传 Epub,会被 pre-commit 所拦截。

下图是开启 LFS 后的提交截图,性能和速度比起 Git 直接提交,要好上不少:

![Pasted image 20240205021126.png](/img/user/998.%E9%99%84%E4%BB%B6%E4%BB%93%E5%BA%93/Pasted%20image%2020240205021126.png)

在 Gitea 项目设置的 LFS Tab 中,能够看到二进制文件:

![Pasted image 20240205021311.png](/img/user/998.%E9%99%84%E4%BB%B6%E4%BB%93%E5%BA%93/Pasted%20image%2020240205021311.png)


---

## 尝试 track 大视频

下面尝试添加开头说的那个 3.4GB 的大视频。上传过程中速度非常快(这是我电脑 WIFI 的速度上限):

{{CODE_BLOCK_5}}

值得一提的是,这个过程电脑负载非常轻。Server 端压力也小得多。Git 直接处理二进制时,性能开销很大,同时在 Server 侧需要申请大量内存。而有了 Git LFS,实际上就是一个接口文件上传的事情。

---

## 暂时关闭 [[obsidian-git]] 自动同步

这套系统配置好后,我准备手动同步一段时间。在这段时间里,细细查看过程中是否有什么问题。等到未来,打磨流畅、有了足够信心后,再将 [[obsidian-git]] 自动同步打开,这件事情便彻底完结了。

---

## 新电脑配置 Todo

未来新电脑需要 clone repo 时,需要遵循以下步骤:

1. 电脑安装 [[Git LFS]]
2. clone 仓库
3. 需要手动复制 `pre-commit` 脚本,放入 `.git/hooks` 目录下



本文作者:Maeiee

本文链接:Obsidian obsidian-git 使用 Git LFS 管理大文件

版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!


喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!